#include <iostream>

class MyString{
    private:
        char * m_data;
        size_t m_len;
        void copy_data(const char *)
        {
        }

    public:
        //两个构造函数
        MyString(){}
        MyString(const char *p){}

        //拷贝构造
        MyString(const MyString &str){
            m_len = str.m_len;
            copy_data(str.m_data);
        }//常量左值拷贝构造函数
        //赋值构造
        MyString & operator=(const MyString & str){
            if(this != &str)
            {
                m_len = str.m_len;
                copy_data(str.m_data);
            }
        } //常量左值赋值构造函数

        //===上面两个都会有额外的内存申请和释放
        //===下面两个使用了移动语义，避免了临时对象的拷贝
        //移动系列的函数：参数是右值引用，但返回值可还是左值引用哦
        MyString(MyString &&str) {
            //移动语义 就是釜底抽薪
            m_len = str.m_len;
            m_data = str.m_data;
            str.m_len = 0;
            str.m_data = nullptr;
        } //移动构造
        MyString & operator=(MyString &&str) {
            if(this != &str)
            {
                m_len = str.m_len;
                m_data = str.m_data;
                str.m_len = 0;
                str.m_data = nullptr;
            }

            return *this;
        } //移动赋值

        virtual ~MyString(){} //析构
};

//有了右值引用和移动句义，在设计和实现类时，对于需要动态申请大量资源的类，应该设计右值引用的拷贝构造函数和赋值函数，以提高应用程序的效率。
//需要注意的是，我们一般在提供右值引用的构造函数时，也会提供常量左值引用的拷贝构造，以保证移动不成，还有拷贝构造
